﻿namespace PowerSong.SongDatabase
    {
    using System;
    using System.Collections.Generic;
    using System.IO;

    /// <summary>
    /// Represents a song, which consists of a title, verses, copyright details, licensing information and assigned categories.
    /// </summary>
    public class Song : BaseEntity
        {

        /// <summary>
        /// Gets or sets the display title of the song.
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Gets the list of the song's authors.
        /// </summary>
        public List<string> Authors { get; private set; }

        /// <summary>
        /// Gets a list of the verses that have been defined for this song.
        /// </summary>
        public List<string> Verses { get; private set; }

        /// <summary>
        /// Gets or sets the copyright details for this song.
        /// </summary>
        public string Copyright { get; set; }

        /// <summary>
        /// Gets or sets the license that this song has been assigned.
        /// </summary>
        public License License { get; set; }

        /// <summary>
        /// Gets or sets the default initial style associated with this song.
        /// </summary>
        public Style DefaultStyle { get; set; }

        /// <summary>
        /// Gets the list of categories that have been assigned to this song.
        /// </summary>
        public List<Category> Categories { get; private set; }

        /// <summary>
        /// Creates a new song, with no title or verses.
        /// </summary>
        public Song()
            : this(string.Empty)
            {
            }

        /// <summary>
        /// Creates a new song, with the given title and verses.
        /// </summary>
        /// <param name="title">The title of this song.</param>
        /// <param name="verses">A list of verses to give to this song.</param>
        public Song(string title, params string[] verses)
            : base(FileEntryType.Song, 1)
            {
            this.Title = title;
            this.Authors = new List<string>();
            this.Verses = new List<string>(verses);
            this.Categories = new List<Category>();
            this.Copyright = string.Empty;
            }

        internal override bool Deserialise(Database database, BinaryReader reader, int version)
            {

            // Ensure the version is correct
            if (version != 1) return false;

            // Get title
            this.Title = reader.ReadString();

            // Get the authors
            var authorCount = reader.ReadInt32();
            this.Authors.Clear();
            for (var authorIndex = 0; authorIndex < authorCount; authorIndex++)
                {
                this.Authors.Add(reader.ReadString());
                }

            // Get the verses
            var verseCount = reader.ReadInt32();
            this.Verses.Clear();            
            for (var verseIndex = 0; verseIndex < verseCount; verseIndex++)
                {
                this.Verses.Add(reader.ReadString());
                }

            // Get categories
            var categoryCount = reader.ReadInt32();
            this.Categories.Clear();
            for (var categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++)
                {
                var categoryID = new Guid(reader.ReadBytes(16));
                this.Categories.Add(database.Categories.Get(categoryID));
                }

            // Get copyright details
            this.Copyright = reader.ReadString();

            // Get license (note that it is acceptable to have an ID for a license that does not exist - ie perhaps it was deleted?)
            var licenseID = new Guid(reader.ReadBytes(16));
            this.License = database.Licenses.Get(licenseID);

            // Get default style (note that it is acceptable to have an ID for a style that does not exist - ie perhaps it was deleted?)
            var styleID = new Guid(reader.ReadBytes(16));
            this.DefaultStyle = database.Styles.Get(styleID);

            // Details read in successfully
            return true;

            }

        internal override void Serialise(BinaryWriter writer)
            {

            // Write title
            writer.Write(Title);

            // Write authors
            writer.Write(Authors.Count);
            foreach (var author in Authors)
                {
                writer.Write(author);
                }

            // Write verses
            writer.Write(Verses.Count);
            foreach (var verse in Verses)
                {
                writer.Write(verse);
                }

            // Write categories
            writer.Write(Categories.Count);
            foreach (var category in Categories)
                {
                writer.Write(category.ID.ToByteArray());
                }

            // Write copyright details
            writer.Write(Copyright);

            // Write license
            var licenseID = License == null ? Guid.Empty : License.ID;
            writer.Write(licenseID.ToByteArray());

            // Write default style
            var styleID = DefaultStyle == null ? Guid.Empty : DefaultStyle.ID;
            writer.Write(styleID.ToByteArray());

            }

        /// <summary>
        /// Returns the title of the song.
        /// </summary>
        /// <returns>The title of the song.</returns>
        public override string ToString()
            {
            return Title;
            }

        }

    }
